﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../RANGE.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace RANGEDecoder
{
// clang-format off
using Sync      = TAO_PEGTL_STRING("#RANGEA");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
struct Obs : star<digit> {};
struct PrnSlot : star<digit> {};
struct Glofreq : star<digit> {};
struct PSR : Floating {};
struct PSRSigma : Floating {};
struct ADR : Floating {};
struct ADRSigma : Floating {};
struct DOPP : Floating {};
struct CNo : Floating {};
struct LockTime : Floating {};
struct ChTrStatus : star<xdigit> {};
// clang-format on
using PRN = seq<Split,
                PrnSlot,
                Split,
                Glofreq,
                Split,
                PSR,
                Split,
                PSRSigma,
                Split,
                ADR,
                Split,
                ADRSigma,
                Split,
                DOPP,
                Split,
                CNo,
                Split,
                LockTime,
                Split,
                ChTrStatus>;

using Expression = seq<Header, Obs, star<PRN>, one<'*'>, CRC32, Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<Obs> : IntHelper<Action<Obs>, uint32_t>
{
    static void setValue(RANGE::Data& data, uint32_t value) { data.obs = value; }
};

template<>
struct Action<PrnSlot> : IntHelper<Action<PrnSlot>, uint16_t>
{
    static void setValue(RANGE::Data& data, uint16_t value)
    {
        data.prns.emplace_back(RANGE::Data::PRN {});
        data.prns.back().prnSlot = value;
    }
};

template<>
struct Action<Glofreq> : IntHelper<Action<Glofreq>, uint16_t>
{
    static void setValue(RANGE::Data& data, uint16_t value) { data.prns.back().glofreq = value; }
};

template<>
struct Action<PSR> : DoubleHelper<Action<PSR>>
{
    static void setValue(RANGE::Data& data, double value) { data.prns.back().psr = value; }
};

template<>
struct Action<PSRSigma> : FloatHelper<Action<PSRSigma>>
{
    static void setValue(RANGE::Data& data, float value) { data.prns.back().psrSigma = value; }
};

template<>
struct Action<ADR> : DoubleHelper<Action<ADR>>
{
    static void setValue(RANGE::Data& data, double value) { data.prns.back().adr = value; }
};

template<>
struct Action<ADRSigma> : FloatHelper<Action<ADRSigma>>
{
    static void setValue(RANGE::Data& data, float value) { data.prns.back().adrSigma = value; }
};

template<>
struct Action<DOPP> : FloatHelper<Action<DOPP>>
{
    static void setValue(RANGE::Data& data, float value) { data.prns.back().dopp = value; }
};

template<>
struct Action<CNo> : FloatHelper<Action<CNo>>
{
    static void setValue(RANGE::Data& data, float value) { data.prns.back().cNo = value; }
};

template<>
struct Action<LockTime> : FloatHelper<Action<LockTime>>
{
    static void setValue(RANGE::Data& data, float value) { data.prns.back().locktime = value; }
};

template<>
struct Action<ChTrStatus> : IntHelper<Action<ChTrStatus>, uint32_t, 16>
{
    static void setValue(RANGE::Data& data, uint32_t value) { data.prns.back().chTrStatus.data = value; }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(RANGE::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace RANGEDecoder
} // namespace GnssLogs